package main

import (
	"github.com/gin-gonic/gin"
	"log"
	//"github.com/fvbock/endless"
	"context"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
	"sync"
)
var RQCount int
var RQClosed bool
var MU sync.Mutex
func addRQCount()  {
	MU.Lock()
	RQCount += 1
	MU.Unlock()
}

func delRQCount()  {
	MU.Lock()
	RQCount -= 1
	if RQCount < 0{
		RQCount=0
	}
	MU.Unlock()
}

func main() {
	r := gin.Default()

	r.GET("/", func(context *gin.Context) {
		log.Println("You are accept / for api version")
		context.JSON(http.StatusOK, gin.H{"version": "1.0"})
	})
	r.GET("/long_async", func(context *gin.Context) {
		log.Println("You are accept /long_async for async")
		cCp := context.Copy()
		if RQClosed {
			context.JSON(http.StatusForbidden, gin.H{"Status": "Server is Closing..."})
			return
		}
		go func() {
			addRQCount()
			defer delRQCount()
			log.Println("async start! RQCount:", RQCount)
			for i := 0; i < 20; i++ {
				time.Sleep(1 * time.Second)
			}
			log.Println("async Done! RQCount:", RQCount)
			log.Println("async Done! path:", cCp.Request.URL.Path)
		}()
		context.JSON(http.StatusOK, gin.H{"long_async": "haha Success"})
	})
	r.GET("/long_sync", func(context *gin.Context) {
		time.Sleep(5 * time.Second)
		log.Println("sync Done! path:", context.Request.URL.Path)
		context.JSON(http.StatusOK, gin.H{"long_sync": "haha Success"})
	})
	//r.Run(":8080")
	//endless.ListenAndServe(":8080", r)
	server := &http.Server{
		Addr:    ":8080",
		Handler: r,
	}
	go func() {
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("listen: %s\n", err)
		}
	}()
	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
	log.Println("Shutdown Server ...")
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()
	RQClosed = true
	log.Println("Server Shutdown! RQClosed:", RQClosed)
	log.Println("Server Shutdown! RQCount:", RQCount)
	for {
		if RQCount == 0 {
			if err := server.Shutdown(ctx); err != nil {
				log.Fatal("Server shutdown err:", err)
			}
			break
		}
		time.Sleep(1*time.Second)
	}
	//if err := server.Shutdown(ctx); err != nil {
	//	log.Fatal("Server shutdown err:", err)
	//}
	//select {
	//case <-ctx.Done():
	//	log.Println("timeout of 30 seconds.")
	//}
	log.Println("Server exiting")
}
